home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1993 / Internet Info CD-ROM (Walnut Creek) (1993).iso / networking / ip / ka9q / osrc.arc / TELNET.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-05  |  6.9 KB  |  343 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "socket.h"
  5. #include "telnet.h"
  6. #include "session.h"
  7. #include "proc.h"
  8. #include "tty.h"
  9.  
  10. #define    CTLZ    26
  11.  
  12. extern char Nospace[];
  13. extern char Badhost[];
  14. void tel_input();
  15. static void doopt(),dontopt(),willopt(),wontopt(),answer();
  16. void answer();
  17.  
  18. int Refuse_echo = 0;
  19. int Unix_line_mode = 0;    /* if true turn <cr> to <nl> when in line mode */
  20.  
  21. #ifdef    DEBUG
  22. char *T_options[] = {
  23.     "Transmit Binary",
  24.     "Echo",
  25.     "",
  26.     "Suppress Go Ahead",
  27.     "",
  28.     "Status",
  29.     "Timing Mark"
  30. };
  31. #endif
  32.  
  33. /* Execute user telnet command */
  34. int
  35. dotelnet(argc,argv)
  36. int argc;
  37. char *argv[];
  38. {
  39.     struct telnet tn;
  40.     struct sockaddr_in fsocket;
  41.     struct mbuf *bp;
  42.     char *cp;
  43.     struct session *sp;
  44.  
  45.     /* Allocate a session descriptor */
  46.     if((sp = newsession(argv[1],TELNET)) == NULLSESSION){
  47.         printf("Too many sessions\n");
  48.         return 1;
  49.     }
  50.     /* Initialize Telnet protocol descriptor */
  51.     memset((char *)&tn,0,sizeof(tn));
  52.     tn.output = Curproc;
  53.     tn.session = sp;    /* Upward pointer */
  54.     sp->cb.telnet = &tn;    /* Downward pointer */
  55.  
  56.     fsocket.sin_family = AF_INET;
  57.     if(argc < 3)
  58.         fsocket.sin_port = IPPORT_TELNET;
  59.     else
  60.         fsocket.sin_port = atoi(argv[2]);
  61.  
  62.     Current = sp;
  63.     Mode = CONV_MODE;
  64.     if((fsocket.sin_addr.s_addr = resolve(sp->name)) == 0){
  65.         printf(Badhost,sp->name);
  66.         freesession(sp);
  67.         return 1;
  68.     }
  69.     if((sp->s = socket(AF_INET,SOCK_STREAM,0)) == -1){
  70.         printf("Can't create socket\n");
  71.         freesession(sp);
  72.         return 1;
  73.     }
  74.     printf("Trying %s...\n",psocket((struct sockaddr *)&fsocket));
  75.     if(connect(sp->s,(char *)&fsocket,SOCKSIZE) == -1){
  76.         cp = sockerr(sp->s);
  77.         printf("Telnet session %u connect failed: %s\n",
  78.          (unsigned)(sp-Sessions),cp != NULLCHAR ? cp : "");
  79.         freesession(sp);
  80.         return 1;
  81.     }
  82.     printf("Telnet session %u connected to %s\n",
  83.         (unsigned)(sp-Sessions),sp->name);
  84.     /* Fork off the receiver process */
  85.     tn.input = newproc("tel_in",512,tel_input,0,&tn,NULL);
  86.  
  87.     /* Now send whatever's typed on the terminal */
  88.     for(;;){
  89.         while(sp->input == NULLBUF)
  90.             if(pwait(&sp->input) == -1)
  91.                 goto quit;
  92.  
  93.         bp = dequeue(&sp->input);
  94.  
  95.         /* If we're doing our own echoing and recording is enabled,
  96.          * record it
  97.          */
  98.         if(!tn.remote[TN_ECHO] && sp->record != NULLFILE)
  99.             write_p(sp->record,bp);
  100.         if(send_mbuf(sp->s,bp,0,NULLCHAR,0) == -1)
  101.             break;
  102.     }
  103. quit:    close_s(sp->s);
  104.     killproc(tn.input);
  105.     freesession(sp);
  106.     return 0;
  107. }
  108.  
  109. /* User telnet receive task, started by user telnet command */
  110. void
  111. tel_input(unused,tn)
  112. int unused;
  113. struct telnet *tn;
  114. {
  115.     int c;
  116.     FILE *record;
  117.     struct session *sp;
  118.     char *cp;
  119.     struct mbuf *bp = NULLBUF;
  120.  
  121.     sp = tn->session;
  122.  
  123.     while((c = recvchar(sp->s,&bp)) != -1){
  124.  
  125.         /* Suspend output if we're not current */
  126.         while(Current != sp || Mode != CONV_MODE)
  127.             if(pwait(sp) == -1)
  128.                 goto quit;
  129.  
  130.         if(uchar(c) == IAC){
  131.             /* IAC received, get command sequence */
  132.             c = recvchar(sp->s,&bp);
  133.             switch(uchar(c)){
  134.             case WILL:
  135.                 willopt(tn,recvchar(sp->s,&bp));
  136.                 break;
  137.             case WONT:
  138.                 wontopt(tn,recvchar(sp->s,&bp));
  139.                 break;
  140.             case DO:
  141.                 doopt(tn,recvchar(sp->s,&bp));
  142.                 break;
  143.             case DONT:
  144.                 dontopt(tn,recvchar(sp->s,&bp));
  145.                 break;
  146.             case IAC:    /* Escaped IAC */
  147.                 putchar(IAC);
  148.                 if((record = sp->record) != NULLFILE)
  149.                     putc(IAC,record);
  150.                 break;
  151.             }
  152.         } else {
  153.             /* Ordinary character */
  154.             if(!tn->remote[TN_TRANSMIT_BINARY])
  155.                 c &= 0x7f;
  156.  
  157.             putchar(c);
  158.             if((record = sp->record) != NULLFILE)
  159.                 putc(c,record);
  160.         }
  161.     }
  162. quit:    /* Close seen from remote host */
  163.     free_p(bp);
  164.     cp = sockerr(sp->s);
  165.     printf("Telnet session %u closed: %s\n", (unsigned)(sp - Sessions),
  166.      cp != NULLCHAR ? cp : "EOF");
  167.     close_s(sp->s);
  168.     killproc(tn->output);
  169.     freesession(sp);
  170. }
  171.  
  172. /* File uploading task */
  173. void
  174. tel_upload(unused,sp)
  175. int unused;
  176. struct session *sp;
  177. {
  178.     struct telnet *tn;
  179.     struct mbuf *bp;
  180.  
  181.     tn = sp->cb.telnet;
  182.     for(;;){
  183.         bp = alloc_mbuf(BUFSIZ);
  184.         bp->cnt = fread(bp->data,1,BUFSIZ,sp->upload);
  185.         if(bp->cnt != 0){
  186.             send_mbuf(sp->s,bp,0,NULLCHAR,0);
  187.         } else {
  188.             free_p(bp);
  189.             break;
  190.         }
  191.     }
  192.     fclose(sp->upload);
  193.     sp->upload = NULLFILE;
  194.     free(sp->ufile);
  195.     sp->ufile = NULLCHAR;
  196.     tn->upload = NULLPROC;
  197. }
  198. /* The guts of the actual Telnet protocol: negotiating options */
  199. static
  200. void
  201. willopt(tn,opt)
  202. struct telnet *tn;
  203. char opt;
  204. {
  205.     int ack;
  206.  
  207. #ifdef    DEBUG
  208.     printf("recv: will ");
  209.     if(uchar(opt) <= NOPTIONS)
  210.         printf("%s\n",T_options[opt]);
  211.     else
  212.         printf("%u\n",opt);
  213. #endif
  214.     
  215.     switch(uchar(opt)){
  216.     case TN_TRANSMIT_BINARY:
  217.     case TN_ECHO:
  218.     case TN_SUPPRESS_GA:
  219.         if(tn->remote[uchar(opt)] == 1)
  220.             return;        /* Already set, ignore to prevent loop */
  221.         if(uchar(opt) == TN_ECHO){
  222.             if(Refuse_echo){
  223.                 /* User doesn't want to accept */
  224.                 ack = DONT;
  225.                 break;
  226.             } else
  227.                 ttysetmode(0);        /* Put tty into raw mode */
  228.         }
  229.         tn->remote[uchar(opt)] = 1;
  230.         ack = DO;            
  231.         break;
  232.     default:
  233.         ack = DONT;    /* We don't know what he's offering; refuse */
  234.     }
  235.     answer(tn,ack,opt);
  236. }
  237. static
  238. void
  239. wontopt(tn,opt)
  240. struct telnet *tn;
  241. char opt;
  242. {
  243. #ifdef    DEBUG
  244.     printf("recv: wont ");
  245.     if(uchar(opt) <= NOPTIONS)
  246.         printf("%s\n",T_options[uchar(opt)]);
  247.     else
  248.         printf("%u\n",uchar(opt));
  249. #endif
  250.     if(uchar(opt) <= NOPTIONS){
  251.         if(tn->remote[uchar(opt)] == 0)
  252.             return;        /* Already clear, ignore to prevent loop */
  253.         tn->remote[uchar(opt)] = 0;
  254.         if(uchar(opt) == TN_ECHO)
  255.             ttysetmode(TTY_ECHO|TTY_EDIT);    /* Put tty into cooked mode */
  256.     }
  257.     answer(tn,DONT,opt);    /* Must always accept */
  258. }
  259. static
  260. void
  261. doopt(tn,opt)
  262. struct telnet *tn;
  263. char opt;
  264. {
  265.     int ack;
  266.  
  267. #ifdef    DEBUG
  268.     printf("recv: do ");
  269.     if(uchar(opt) <= NOPTIONS)
  270.         printf("%s\n",T_options[uchar(opt)]);
  271.     else
  272.         printf("%u\n",uchar(opt));
  273. #endif
  274.     switch(uchar(opt)){
  275. #ifdef    FUTURE    /* Use when local options are implemented */
  276.         if(tn->local[uchar(opt)] == 1)
  277.             return;        /* Already set, ignore to prevent loop */
  278.         tn->local[uchar(opt)] = 1;
  279.         ack = WILL;
  280.         break;
  281. #endif
  282.     default:
  283.         ack = WONT;    /* Don't know what it is */
  284.     }
  285.     answer(tn,ack,opt);
  286. }
  287. static
  288. void
  289. dontopt(tn,opt)
  290. struct telnet *tn;
  291. char opt;
  292. {
  293. #ifdef    DEBUG
  294.     printf("recv: dont ");
  295.     if(uchar(opt) <= NOPTIONS)
  296.         printf("%s\n",T_options[uchar(opt)]);
  297.     else
  298.         printf("%u\n",uchar(opt));
  299. #endif
  300.     if(uchar(opt) <= NOPTIONS){
  301.         if(tn->local[uchar(opt)] == 0){
  302.             /* Already clear, ignore to prevent loop */
  303.             return;
  304.         }
  305.         tn->local[uchar(opt)] = 0;
  306.     }
  307.     answer(tn,WONT,opt);
  308. }
  309. static
  310. void
  311. answer(tn,r1,r2)
  312. struct telnet *tn;
  313. int r1,r2;
  314. {
  315.     char s[3];
  316.  
  317. #ifdef    DEBUG
  318.     switch(r1){
  319.     case WILL:
  320.         printf("sent: will ");
  321.         break;
  322.     case WONT:
  323.         printf("sent: wont ");
  324.         break;
  325.     case DO:
  326.         printf("sent: do ");
  327.         break;
  328.     case DONT:
  329.         printf("sent: dont ");
  330.         break;
  331.     }
  332.     if(r2 <= 6)
  333.         printf("%s\n",T_options[r2]);
  334.     else
  335.         printf("%u\n",r2);
  336. #endif
  337.  
  338.     s[0] = IAC;
  339.     s[1] = r1;
  340.     s[2] = r2;
  341.     send(tn->session->s,s,3,0);
  342. }
  343.